////////////////////////////////////////////////////////////////////////////////
// Filename: color.hs
////////////////////////////////////////////////////////////////////////////////

/////////////
// GLOBALS //
/////////////

cbuffer MatrixBuffer: register (b0)
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

cbuffer CameraBuffer: register (b1)
{
	float4 cameraPosition;
};


//////////////
// TYPEDEFS //
//////////////
struct HullInputType
{
	float4 pos          : SV_POSITION;         //posizione
    float3 norm         : NORMAL;           //normale
    float3 tan			: TANGENT;          //tangente
    float3 binorm       : BINORMAL;			//binormale
    float2 tex			: TEXCOORD0;			//Coordinate texture
	float3 view			: POSITION0;
};

struct ConstantOutputType
{
    float edges[3] : SV_TessFactor;
    float inside : SV_InsideTessFactor;
};

struct HullOutputType
{
	float4 pos          : SV_POSITION;         //posizione
    float3 norm         : NORMAL;           //normale
    float3 tan			: TANGENT;          //tangente
    float3 binorm       : BINORMAL;			//binormale
    float2 tex			: TEXCOORD0;			//Coordinate texture
	float3 view			: POSITION0;
};


////////////////////////////////////////////////////////////////////////////////
// Patch Constant Function
////////////////////////////////////////////////////////////////////////////////
ConstantOutputType TessPatchConstantFunction(InputPatch<HullInputType, 3> inputPatch, uint patchId : SV_PrimitiveID)
{    
    ConstantOutputType output;

	// Set the tessellation factors for the three edges of the triangle
	float4 worldpos1 = mul(inputPatch[0].pos, worldMatrix);
	float4 worldpos2 = mul(inputPatch[1].pos, worldMatrix);
	float4 worldpos3 = mul(inputPatch[2].pos, worldMatrix);
	//todo : log function distance based...
	float4 disvector = (worldpos1 - cameraPosition + worldpos2 - cameraPosition + worldpos3 - cameraPosition) * 0.25;

	float fTessAmount = length(disvector); 
	fTessAmount = 60 - clamp(fTessAmount,0,55);
	float tessBase = fTessAmount /*60 - abs(cameraPosition.z)*/;

    output.edges[0] = tessBase;
    output.edges[1] = tessBase;
    output.edges[2] = tessBase;

	// Set the tessellation factor for tessallating inside the triangle.
    output.inside = tessBase;

    return output;
}


////////////////////////////////////////////////////////////////////////////////
// Hull Shader
////////////////////////////////////////////////////////////////////////////////
[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("TessPatchConstantFunction")]
HullOutputType TessHullShader(InputPatch<HullInputType, 3> patch, uint pointId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)
{
    HullOutputType output;

    output.pos		= patch[pointId].pos;
	output.norm		= patch[pointId].norm;
	output.tan		= patch[pointId].tan;
	output.binorm	= patch[pointId].binorm;
    output.tex		= patch[pointId].tex;
	output.view		= patch[pointId].view;

    return output;
}
